//////////////////////////////////////////////////////////////////
//****************************************************************
//* File containing the management of all events.
//*
//* Adelailson Peixoto e Fabio Franco 05/05/2003
//* Visgraf - IMPA
//*
//****************************************************************
//////////////////////////////////////////////////////////////////

#include "Image.h"


Image::Image()
{
  width = height = 1;
  r = new unsigned char[width*height];
  g = new unsigned char[width*height];
  b = new unsigned char[width*height];
  rgb = new unsigned char[3*width*height];

  strcpy(fileimg," ");
  width=0; height=0; type=0; tam_pal=0;
  r=g=b=rgb=NULL;
}
////////////////////////////////////////////////
Image::Image(int w, int h)
{
  width = w;
  height = h;
  r = new unsigned char[width*height];
  g = new unsigned char[width*height];
  b = new unsigned char[width*height];
  rgb = new unsigned char[3*width*height];

  for(int j=0; j<height; j++)
  {
    for(int i=0; i<width; i++)
    {
      r[i+j*width]=0;
      g[i+j*width]=0;
      b[i+j*width]=0;
    }
  }

  for(int j=0; j<(3*width*height); j++)
  {
    rgb[j]=0;
  }

  strcpy(fileimg," ");
  type=0; tam_pal=0;
}
////////////////////////////////////////////////
Image::Image(int w, int h, int format, unsigned char *redgreenblue, char *f)
{
  int i, j;

  r = new unsigned char[w*h];
  g = new unsigned char[w*h];
  b = new unsigned char[w*h];
  rgb = new unsigned char[3*w*h];

  //	if(redgreenblue==NULL) return 0;
  //	if(f==NULL) return 0;

  //	if((red=new unsigned char[w*h])==NULL) return 0;
  //	if((green=new unsigned char[w*h])==NULL){delete[]red; return 0;}
  //	if((blue=new unsigned char[w*h])==NULL){delete[]red; delete[]green;return 0;}

  for(i=0; i<(3*w*h); i++)
  {
    rgb[i] = redgreenblue[i];
  }

  for(i=0,j=0; i<(w*h); i++,j+=3)
  {
    r[i] = redgreenblue[j];
    g[i] = redgreenblue[j+1];
    b[i] = redgreenblue[j+2];
  }
  
  width = w;
  height = h;

  type = format;

  tam_pal = 0;

  strcpy(fileimg, f);
}
/////////////////////////////////////////////////
Image::~Image(void)
{
  Unload();
}
/////////////////////////////////////////////////
int Image::Load(char *f)
{
  int w,h,t,tp;

  if(imImageInfo(f, &w, &h, &t, &tp)!=IM_ERR_NONE ) return 0;
  strcpy(fileimg,f);
  width=w; height=h; type=t; tam_pal=tp;

  if (r) delete[]r;
  if (g) delete[]g;
  if (b) delete[]b;
  if (rgb) delete[]rgb;
  
  if((r=new unsigned char[w*h])==NULL) return 0;
  if((g=new unsigned char[w*h])==NULL){delete[]r; return 0;}
  if((b=new unsigned char[w*h])==NULL){delete[]r; delete[]g;return 0;}
  if((rgb=new unsigned char[3*w*h])==NULL){delete[]r; delete[]g; delete[]b; return 0;}

  imLoadRGB(fileimg, r, g, b);

  int i,j;

  for(i=0,j=0; i<(width*height); i++,j+=3)
  {
    rgb[j]=r[i]; rgb[j+1]=g[i]; rgb[j+2]=b[i];
  }
 
  return 1;
}

/////////////////////////////////////////////////
int Image::Load(char *f, bool invert)
{
  int w,h,t,tp;

  if(imImageInfo(f, &w, &h, &t, &tp)!=IM_ERR_NONE ) return 0;
  strcpy(fileimg,f);
  width=w; height=h; type=t; tam_pal=tp;

  if (r) delete[]r;
  if (g) delete[]g;
  if (b) delete[]b;
  if (rgb) delete[]rgb;
  
  if((r=new unsigned char[w*h])==NULL) return 0;
  if((g=new unsigned char[w*h])==NULL){delete[]r; return 0;}
  if((b=new unsigned char[w*h])==NULL){delete[]r; delete[]g;return 0;}
  if((rgb=new unsigned char[3*w*h])==NULL){delete[]r; delete[]g; delete[]b; return 0;}

  imLoadRGB(fileimg, r, g, b);

  int i,j;

  if (invert==true)
  {
    unsigned char aux;

    for(j=0; j<((int)(height/2)-1); j++)
    {
      for(i=0; i<width; i++)
      {
        aux = r[j*width + i];
        r[j*width + i] = r[(height-j-1)*width + i];
        r[(height-j-1)*width + i] = aux;

        aux = g[j*width + i];
        g[j*width + i] = g[(height-j-1)*width + i];
        g[(height-j-1)*width + i] = aux;

        aux = b[j*width + i];
        b[j*width + i] = b[(height-j-1)*width + i];
        b[(height-j-1)*width + i] = aux;
      }
    }
  }

  for(i=0,j=0; i<(width*height); i++,j+=3)
  {
    rgb[j]=r[i]; rgb[j+1]=g[i]; rgb[j+2]=b[i];
  }

  return 1;
}
/////////////////////////////////////////////////
int Image::Load (Image *img, int ch)
{
  int				i,j,n;
  //unsigned char	*red,*green,*blue;

  type=img->GetType();
  tam_pal=img->GetTamPal();
  img->GetDim(&width,&height);
  n=width*height;
  strcpy(fileimg,"none");

  if (r) delete[]r;
  if (g) delete[]g;
  if (b) delete[]b;
  if (rgb) delete[]rgb;
  
  if((r=new unsigned char[width*height])==NULL) return 0;
  if((g=new unsigned char[width*height])==NULL){delete[]r; return 0;}
  if((b=new unsigned char[width*height])==NULL){delete[]r; delete[]g;return 0;}
  if((rgb=new unsigned char[3*width*height])==NULL){delete[]r; delete[]g; delete[]b; return 0;}

  //img->GetRGB(&red,&green,&blue);

  switch(ch)
  {
  case 'R':
    for(i=0; i<n; i++)
    {
      //r[i]=g[i]=b[i]=red[i];
      r[i]=g[i]=b[i]=img->GetR(i);
    }
    break;
  case 'G':
    for(i=0; i<n; i++)
    {
      //r[i]=g[i]=b[i]=green[i];
      r[i]=g[i]=b[i]=img->GetG(i);
    }
    break;
  case'B':
    for(i=0; i<n; i++)
    {
      //r[i]=g[i]=b[i]=blue[i];
      r[i]=g[i]=b[i]=img->GetB(i);
    }
    break;
  default:
    for(i=0; i<n; i++)
    {
      r[i]=img->GetR(i); g[i]=img->GetG(i); b[i]=img->GetB(i);
      //r[i]=red[i]; g[i]=green[i]; b[i]=blue[i];
    }
  }

  for(i=0,j=0; i<(width*height); i++,j+=3)
  {
    rgb[j]=r[i]; rgb[j+1]=g[i]; rgb[j+2]=b[i];
  }
  
  //delete[]red; delete[]green; delete[]blue;
  
  return 1;
}

/////////////////////////////////////////////////
int Image::LoadSubImage(Image *img, int i0, int j0, int w, int h)
{
  width=w;
  height=h;
  type=img->GetType();
  tam_pal=img->GetTamPal();
  strcpy(fileimg,"none");

  if (r) delete[]r;
  if (g) delete[]g;
  if (b) delete[]b;
  if (rgb) delete[]rgb;

  if((r=new unsigned char[w*h])==NULL) return 0;
  if((g=new unsigned char[w*h])==NULL){delete[]r; return 0;}
  if((b=new unsigned char[w*h])==NULL){delete[]r; delete[]g;return 0;}
  if((rgb=new unsigned char[3*w*h])==NULL){delete[]r; delete[]g; delete[]b; return 0;}

  int i,j;
  for(j=0; j<h; j++)
    for(i=0; i<w; i++)
    {
      r[i+j*width]=img->GetR(i0+i,j0+j);
      g[i+j*width]=img->GetG(i0+i,j0+j);
      b[i+j*width]=img->GetB(i0+i,j0+j);
    }

  for(i=0,j=0; i<(w*h); i++,j+=3)
  {
    rgb[j]=r[i]; rgb[j+1]=g[i]; rgb[j+2]=b[i];
  }

  return 1;
}
/////////////////////////////////////////////////
int Image::CopySubImage(Image *img, int i0, int j0, int w, int h)
{
  int j, jsub, i, isub;

  for(j = j0, jsub = 0; j < j0 + h, jsub < h; j++, jsub++)
  {
    for(i = i0, isub = 0; i < i0 + w, isub < w; i++, isub++)
    {
      r[i+j*width]=img->GetR(isub, jsub);
      g[i+j*width]=img->GetG(isub, jsub);
      b[i+j*width]=img->GetB(isub, jsub);

      rgb[3*i+3*j*width+0]=img->GetR(isub, jsub);
      rgb[3*i+3*j*width+1]=img->GetG(isub, jsub);
      rgb[3*i+3*j*width+2]=img->GetB(isub, jsub);
    }
  }

  return 1;
}
/////////////////////////////////////////////////
int Image::Save(int format, char *f)
{
  if(rgb==NULL) return 0;
  if(f==NULL) return 0;

  imSaveRGB(width, height, format, r, g, b, f);

  return 1;
}
/////////////////////////////////////////////////
int Image::Save(int w, int h, int format, unsigned char *r, unsigned char *g, unsigned char *b, char *f)
{
  if(r==NULL) return 0;
  if(g==NULL) return 0;
  if(b==NULL) return 0;
  if(f==NULL) return 0;

  imSaveRGB(w, h, format, r, g, b, f);

  return 1;
}
/////////////////////////////////////////////////
int Image::Save(int w, int h, int format, unsigned char *rgb, char *f)
{
  unsigned char *red, *green, *blue;
  int i, j;

  if(rgb==NULL) return 0;
  if(f==NULL) return 0;

  if((red=new unsigned char[w*h])==NULL) return 0;
if((green=new unsigned char[w*h])==NULL){delete[]red; return 0;}
  if((blue=new unsigned char[w*h])==NULL){delete[]red; delete[]green;return 0;}

  for(i=0,j=0; i<(w*h); i++,j+=3)
  {
    red[i] = rgb[j];
    green[i] = rgb[j+1];
    blue[i] = rgb[j+2];
  }

  imSaveRGB(w, h, format, red, green, blue, f);
  
  delete[]red; delete[]green; delete[]blue;

  return 1;
}
/////////////////////////////////////////////////
void  Image::GetR(unsigned char **red)
{
  *red=r;
}
/////////////////////////////////////////////////
void  Image::GetG(unsigned char **green)
{
  *green=g;
}

/////////////////////////////////////////////////
void  Image::GetB(unsigned char **blue)
{
  *blue=b;
}
/////////////////////////////////////////////////
void  Image::GetRGB(unsigned char **red,unsigned char **green,unsigned char **blue)
{
  *red=r; *green=g; *blue=b;
}
/////////////////////////////////////////////////
void  Image::GetRGB(unsigned char **r_g_b)
{
  *r_g_b=rgb;
}
/////////////////////////////////////////////////
void  Image::GetDim(int *w, int *h)
{
  *w=width; *h=height;
}

////////////////////////////////////////////////
int  Image::IsEmpty(void)
{
  return ((r==NULL)||(g==NULL)||(b==NULL));
}

////////////////////////////////////////////////
void  Image::Unload(void)
{
  if (r!=NULL) {delete []r; r=NULL;}
  if (g!=NULL) {delete []g; g=NULL;}
  if (b!=NULL) {delete []b; b=NULL;}
  if (rgb!=NULL) {delete []rgb; rgb=NULL;}
  width=height=type=tam_pal=0;
}
///////////////////////////////////////////////
unsigned char   Image::GetR(int i,int j)
{
  if ((i < width) && (j < height) && (i >= 0) && (j >= 0)){
    return r[i+j*width];
  }else{
    return 0;
  }
}

///////////////////////////////////////////////
unsigned char   Image::GetR(int i)
{
  if ((i < width*height) && (i >= 0)){
    return r[i];
  }else{
    return 0;
  }
}
///////////////////////////////////////////////
unsigned char   Image::GetG(int i,int j)
{
  if ((i < width) && (j < height) && (i >= 0) && (j >= 0)){
    return g[i+j*width];
  }else{
    return 0;
  }
}
///////////////////////////////////////////////
unsigned char   Image::GetG(int i)
{
  if ((i < width*height) && (i >= 0)){
    return g[i];
  }else{
    return 0;
  }
}
///////////////////////////////////////////////
unsigned char   Image::GetB(int i,int j)
{
  if ((i < width) && (j < height) && (i >= 0) && (j >= 0)){
    return b[i+j*width];
  }else{
    return 0;
  }
}
///////////////////////////////////////////////
unsigned char   Image::GetB(int i)
{
  if ((i < width*height) && (i >= 0)){
    return b[i];
  }else{
    return 0;
  }
}

///////////////////////////////////////////////
void Image::GetRGB(int i, unsigned char *red,unsigned char *green,unsigned char *blue)
{
  *red=r[i];   *green=g[i];   *blue=b[i];
}

///////////////////////////////////////////////
void Image::SetRGB(int i, unsigned char red,unsigned char green,unsigned char blue)
{
  r[i]=red;   g[i]=green;   b[i]=blue;

  int j=3*i;
  rgb[j]=red; rgb[j+1]=green; rgb[j+2]=blue;

}
////////////////////////////////////////////////
void  Image::SetRGB(int i, int j, unsigned char red, unsigned char green, unsigned char blue)
{
  r[i+j*width]=red;
  g[i+j*width]=green;
  b[i+j*width]=blue;

  rgb[3*i+3*j*width+0]=red;
  rgb[3*i+3*j*width+1]=green;
  rgb[3*i+3*j*width+2]=blue;
}
////////////////////////////////////////////////
void  Image::SetRGB(unsigned char *redgreenblue)
{
  int i, j;

  for(i=0; i<(3*width*height); i++)
  {
    rgb[i] = redgreenblue[i];
  }

  for(i=0,j=0; i<(width*height); i++,j+=3)
  {
    r[i] = redgreenblue[j];
    g[i] = redgreenblue[j+1];
    b[i] = redgreenblue[j+2];
  }
}
////////////////////////////////////////////////
void Image::SetType(int t)
{
  type = t;
}
////////////////////////////////////////////////
void Image::SetTamPal(int tam)
{
  tam_pal = tam;
}
///////////////////////////////////////////////
float   Image::GetGray(int i,int j)
{
  float red,green,blue;

  red  = (float) r[i+j*width];
  green= (float) g[i+j*width];
  blue = (float) b[i+j*width];

  return (red+green+blue)/3;
}
///////////////////////////////////////////////

float   Image::GetGray(int i)
{
  float red,green,blue;

  red  = (float) r[i];
  green= (float) g[i];
  blue = (float) b[i];

  return (red+green+blue)/3;
}
